'use strict';
/**
 * 帧动画库类
 * @constructor
 */

let loadImage = require('./imageloader');
var Timeline = require('./timeline');

// 初始状态
let STATE_INITIAL = 0;
// 开始状态
let STATE_START = 1;
// 停止状态
let STATE_STOP = 2;  

// 同步任务
let TASK_SYNC = 0;
// 异步任务
let TASK_ASYNC = 1;

/**
 * 执行函数封装
 * @param {*} callback 
 */
function next(callback) {
    callback && callback();
}
 
function Animation() {
    this.taskQueue = [];
    this.index = 0;

    this.timeline = new Timeline();
    this.state = STATE_INITIAL;
}

/**
 * 添加一个同步任务，去预加载图片
 * @param imglist 图片数组
 */
Animation.prototype.loadImage = function (imglist) {
    let taskFn = function(next) {
        loadImage(imglist.slice(), next);
    };

    let type = TASK_SYNC;
    return this._add(taskFn, type);
};

/**
 * 添加一个异步定时任务，通过定时改变图片背景位置，实现帧动画
 * @param ele 
 * @param positions
 * @param imageUrl
 */

Animation.prototype.changePosition = function (ele, positions, imageUrl) {
    let len = positions.length;
    let taskFn;
    let type;
    if(len){
        let _this = this;
        taskFn = function (next, time) {
            if(imageUrl){
                ele.style.backgroundImage = 'url(' + imageUrl + ')';
            }
            // 获取当前背景索引
            let index = Math.min(time/_this.interval | 0, len-1);
            let position = positions[index].split(' ');
            // 改变DOM对象的背景图片位置
            ele.style.backgroundPosition = position[0] + 'px' + position[1] + 'px';
            if(index === len-1){
                // 异步任务完成，进入下一个任务
                next();
            }

        };
        type = TASK_ASYNC;
    } else{
        taskFn = next;
        type = TASK_SYNC;
    }
    return this._add(taskFn, type);
};

/**
 * 添加一个异步定时任务，通过定时改变image标签的src属性，实现帧动画
 * @param ele 
 * @param imgList
 */

Animation.prototype.changeSrc = function (ele, imgList) {
    let len = positions.length;
    let taskFn;
    let type;
    if(len){
        let _this = this;
        taskFn = function (next, time) {
            // 获取当前图片索引
            let index = Math.min(time/_this.interval | 0, len-1);
            // 改变image对象的图片地址
            ele.src = imgList[index];
            if(index === len-1){
                // 异步任务完成，进入下一个任务
                next();
            }

        };
        type = TASK_ASYNC;
    } else{
        taskFn = next;
        type = TASK_SYNC;
    }
    return this._add(taskFn, type);
};

/**
 * 高级用法，添加一个异步定时执行的任务
 * 该任务自定义动画每帧执行的任务函数
 * @param {定义每一帧执行的任务函数} taskFn
 */
Animation.prototype.enterFrame = function(taskFn) {
    this._add(taskFn, TASK_ASYNC);
};

/**
 * 添加一个同步任务， 可以在上一个任务完成之后执行回调函数
 * @param {回调函数} callback 
 */
Animation.prototype.then = function (callback) {
    let taskFn = function (next) {
       callback();
       next();  
    };
    let type = TASK_SYNC;
    return this._add(taskFn, type);
};

/**
 * 开始执行任务，异步定义任务执行的间隔
 * @param {时间间隔} interval 
 */
Animation.prototype.start = function (interval) {
    if(this.state === STATE_START){
        return this;
    }
    // 如果任务链重没有任务，则返回
    if(!this.taskQueue.length){
        return this;
    }
    this.state = STATE_START;
    this.interval = interval;
    this._runTask();
    return this;
};

/**
 * 添加一个同步任务，该任务就是回退到上一个任务当中
 * 实现重复上一个任务的效果，可以定义重复的次数
 * @param {重复次数} times 
 */
Animation.prototype.repeat = function (times) {
    let _this = this;
    let taskFn = function (params) {
        if(typeof times === 'undefined'){
            // 无限回退到上一个任务
            _this.index--;
            _this._runTask();
            return;
        }
        if(times){
            times --;
            // 回退
            _this.index --;
            _this._runTask();
        } else{
            // 达到重复次数，跳转到下一个方法
            let task = this.taskQueue[_this.index];
            _this._next(task);
        }
    }
    let type = TASK_SYNC;
    return _this._add(taskFn, type);
};

/**
 * 添加一个同步任务，相当于repeat更友好的接口，无限循环上一次任务
 */
Animation.prototype.repeatForever = function () {
    
};

/**
 * 设置当前任务执行结束到下一个任务开始之前的等待时间
 * @param {*} time 
 */
Animation.prototype.wait = function (time) {
    if(this.taskQueue && this.taskQueue.length > 0){
        this.taskQueue[this.taskQueue.length - 1].wait = time;
    }
    return this;
};

/**
 * 暂停当前异步定时任务
 */
Animation.prototype.pause = function () {
    if(this.state = STATE_START){
        this.state = STATE_STOP;
        this.timeline.stop();
        return this;
    }
    return this;
};

/**
 *  重新执行上一次暂停的异步任务
 */
Animation.prototype.restart = function () {
    if(this.state === STATE_STOP){
        this.state = STATE_START;
        this.timeline.restart();
        return this;
    }
    return this;
};

/**
 * 释放资源
 */
Animation.prototype.dispose = function () {
    if(this.state !== STATE_INITIAL){
        this.state = STATE_INITIAL;
        this.taskQueue = null;
        this.timeline.stop();
        this.timeline = null;
        return this;
    }
    return this;
};

/**
 * 添加一个任务到任务队列
 * @param {任务方法} taskFn 
 * @param {任务类型} type
 * @private 
 */
Animation.prototype._add = function (taskFn, type) {
    this.taskQueue.push({
        taskFn: taskFn,
        type: type
    });

    return  this;
};

/**
 * 执行任务
 */
Animation.prototype._runTask = function () {
    if(!this.taskQueue || this.state !== STATE_START){
        return;
    }
    // 任务执行完毕
    if(this.index === this.taskQueue.length){
        this.dispose();
        return;
    }
    // 获得任务链上的当前任务
    let task = this.taskQueue[this.index];
    if(task.type === TASK_SYNC){
        this._syncTask(task);
    }else{
        this._asyncTask(task);
    }
};
/**
 * 同步任务
 * @param {执行任务的对象} task
 * @private 
 */
Animation.prototype._syncTask = function (task) {
    let _this = this;
    let next = function () {
        // 切换到下一个任务
        _this._next(task);
    }

    let taskFn = task.taskFn;
    taskFn(next);
};

/**
 * 异步任务
 * @param {执行任务的对象} task 
 * @private
 */
Animation.prototype._asyncTask = function (task) {
    let _this = this;
    // 定义每一帧的回调函数
    let enterFrame = function (time) {
         let taskFn  = task.taskFn;
         let next = function(){
            // 停止当前任务 
            _this.timeline.stop();
            // 执行下一个任务
            _this._next(task);
         };
         taskFn(next, time);
    };
    this.timeline.onenterframe = enterFrame;
    this.timeline.start(this.interval);
};

/**
 * 切换到下一个任务（如果当前任务需要等待，则延时执行）
 * @param task 当前任务
 * @private
 */

Animation.prototype._next = function (task) {
    this.index ++;
    let _this = this;
    task.wait? setTimeout(function(){
        _this._runTask();
    }, task.wait) : this._runTask();
};

module.exports = function() {
    return new Animation();
};